package action;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.UUID;

import org.json.JSONObject;

import bean.WechatCache;
import service.DepositService;
import service.LuckyService;
import service.WechatCacheService;
import utils.AjaxResult;
import utils.AppConfig;
import utils.DateTimeUtils;
import utils.HttpsRequest;
import utils.SHA1;

public class WechatTicketApi extends BaseAction {

    public static final String REQUEST_API_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    private String openId;
    public static boolean CACHED = false;
    public static String CACHED_API_TICKET = null;
    public static Timestamp API_TICKET_EXPIRES = null;
    
    private WechatCacheService wechatCacheService;
    private WechatAccessTokenApi wechatAccessTokenApi;
    private DepositService depositService;
    private LuckyService luckyService;
    
    public void setWechatAccessTokenApi(WechatAccessTokenApi wechatAccessTokenApi) {
        this.wechatAccessTokenApi = wechatAccessTokenApi;
    }
    
    public void setWechatCacheService(WechatCacheService wechatCacheService) {
        this.wechatCacheService = wechatCacheService;
    }
    
    public void setDepositService(DepositService depositService) {
        this.depositService = depositService;
    }
    
    public void setLuckyService(LuckyService luckyService) {
        this.luckyService = luckyService;
    }
    
    public String getOpenId() {
        return openId;
    }
    
    public void setOpenId(String openId) {
        this.openId = openId;
    }
    
    public String getTicketInfo() {

//        openId = "ol-ZLt42QCylIQbUXxUsUFEAvVCU";
        
        AjaxResult result = null;
        if (isNullOrEmptyString(openId)) {
            result = new AjaxResult(AjaxResult.CODE_ERROR, "缺少微信账号信息，2秒后跳转到首页");
            result.addData("noOpenId", true);
        } else{
            String ticket = getApiTicket();
            
            if (ticket == null) { 
                result = new AjaxResult(AjaxResult.CODE_ERROR, "获取卡券失败");
                return ERROR;
            }
            
            String timestamp = create_timestamp();
            String nonceStr = create_nonce_str();
            if(nonceStr.length() > 32) {
                nonceStr = nonceStr.substring(0, 31);
            }
            int type = luckyService.getType(openId);
            System.out.println("card type:"+type);
            String cardId = type == 0 ? AppConfig.CARD_ID : AppConfig.CARD_ID2;
                
            System.out.println("openId = "+openId+"\nticket = "+ticket+"\ncardId = "+cardId+"\ntimestamp = "+timestamp+"\nnonceStr = "+nonceStr);
                   
            String[] str = { ticket, timestamp, nonceStr, cardId };
            Arrays.sort(str); // 排序
            
            String resort = str[0] + str[1] + str[2] + str[3];
            String signature = new SHA1().getDigestOfString(resort.getBytes()).toLowerCase();
            System.out.println("signature="+signature);

            result = new AjaxResult(AjaxResult.CODE_SUCCESS, "success");
            result.addData("timestamp", timestamp);
            result.addData("nonceStr", nonceStr);
            result.addData("openid", openId);
            result.addData("cardId", cardId);
            result.addData("signature", signature);
            result.addData("type", type+"");
            
            try {
                inputStream = new ByteArrayInputStream(result.toString().getBytes("UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
       
        return SUCCESS;
    }
    
    
    /**
     * Get Jsapi ticket
     * @return
     */
    public String getApiTicket() {
        // Attempt to get jsapi ticket from cache
        String ticket = getApiTicketFromCache();
        if (ticket != null) {
            return ticket;
        }
        
        // attempt to get jsapi ticket from database
        ticket = getApiTicketFromDatabase();
        if (ticket != null) {
            return ticket;
        }
        
        // request jsapi ticket from wechat server
        ticket = getApiTicketFromWechatServer();
        return ticket;
    }
    
    /**
     * Attempt to get api ticket from database
     * @return
     */
    private String getApiTicketFromDatabase() {
        // get last cache from database
        WechatCache cache = wechatCacheService.getLast();
        
        // if the ticket has been cached, token and expires are exist
        if (cache != null && cache.getApiTicket() != null && cache.getApiTicketExpires() != null) {
            // and the cached token does not expires
            Timestamp now = DateTimeUtils.generateTimestamp();
            if (cache.getApiTicketExpires().after(now)) {
                // update the ROM cache
                CACHED = false;
                CACHED_API_TICKET = cache.getApiTicket();
                API_TICKET_EXPIRES = new Timestamp(cache.getApiTicketExpires().getTime());
                CACHED = true;
                
                // return the token
                return cache.getApiTicket();
            }
        }
        
        return null;
    }

    /**
     * Attempt to get api ticket from cache
     * @return
     */
    private String getApiTicketFromCache() {
        // the jsapi ticket has been cached, token and expires are exist
        if (CACHED && CACHED_API_TICKET != null && API_TICKET_EXPIRES != null) {
            // and the cached ticket does not expires
            Timestamp now = DateTimeUtils.generateTimestamp();
            if (API_TICKET_EXPIRES.after(now)) {
                return CACHED_API_TICKET;
            }
        }
        
        // otherwise
        CACHED = false;
        return null;
    }

    /**
     * Request access token from wechat server
     * @return
     */
    private String getApiTicketFromWechatServer() {
        String token = wechatAccessTokenApi.getAccessToken();
        if (token == null) {
            return null;
        }
        
        String ticket = null;
        
        // 构造参数
        StringBuilder builder = new StringBuilder();
        builder.append("access_token=").append(token.trim()).append("&type=wx_card");
        
        // 请求时间
        Timestamp now = DateTimeUtils.generateTimestamp();
        
        // 获取返回结果
        String response = null;
        try {
            response = HttpsRequest.sendGet(REQUEST_API_TICKET_URL, builder.toString());
        } catch (Exception e) {
            response = null;
        }
        
        // 处理返回结果
        if (response == null) {
            // 获取失败
            ticket = null;
        } else {
            // 解析返回数据
            JSONObject obj = new JSONObject(response);
            if (obj.has("ticket") && obj.has("expires_in")) {
                // 获取成功
                ticket = obj.getString("ticket");
                int expires = obj.getInt("expires_in");
                
                // 更新ROM Cache
                CACHED_API_TICKET = ticket;
                API_TICKET_EXPIRES = new Timestamp(now.getTime() + expires * 1000);
                CACHED = true;
                
                // 更新数据库Cache
                WechatCache cache = new WechatCache(null, null, null, null,
                        ticket, new Timestamp(now.getTime() + expires * 1000));
                wechatCacheService.saveOrUpdateApiTicket(cache);
            }
        }
        
        return ticket;
    }
    
    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}
